home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / PROGRAMR / OLE2BOOK.ZIP / CHAP08.ZIP / CHAP08 / COSCHMOO / DOCUMENT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-18  |  20.9 KB  |  964 lines

  1. /*
  2.  * DOCUMENT.CPP
  3.  * Component Schmoo Chapter 8
  4.  *
  5.  * Implementation of the CSchmooDoc derivation of CDocument as
  6.  * well as an implementation of CPolylineAdviseSink.
  7.  *
  8.  * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  9.  *
  10.  * Kraig Brockschmidt, Software Design Engineer
  11.  * Microsoft Systems Developer Relations
  12.  *
  13.  * Internet  :  kraigb@microsoft.com
  14.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  15.  */
  16.  
  17.  
  18. #include "coschmoo.h"
  19.  
  20.  
  21.  
  22. /*
  23.  * CSchmooDoc::CSchmooDoc
  24.  * CSchmooDoc::~CSchmooDoc
  25.  *
  26.  * Constructor Parameters:
  27.  *  hInst           HINSTANCE of the application.
  28.  */
  29.  
  30. CSchmooDoc::CSchmooDoc(HINSTANCE hInst)
  31.     : CDocument(hInst)
  32.     {
  33.     m_uPrevSize=SIZE_RESTORED;
  34.     m_pPL=NULL;
  35.     m_pIPersistStorage=NULL;
  36.  
  37.     m_pIAdviseSink=NULL;
  38.     m_dwConn=0;
  39.  
  40.     //CHAPTER8MOD
  41.     m_pDropTarget=NULL;
  42.     m_fDragSource=FALSE;
  43.     //End CHAPTER8MOD
  44.  
  45.     return;
  46.     }
  47.  
  48.  
  49. CSchmooDoc::~CSchmooDoc(void)
  50.     {
  51.     LPDATAOBJECT        pIDataObject;
  52.     HRESULT             hr;
  53.  
  54.     //CHAPTER8MOD
  55.     if (NULL!=m_pDropTarget)
  56.         {
  57.         RevokeDragDrop(m_hWnd);
  58.         CoLockObjectExternal((LPUNKNOWN)m_pDropTarget, FALSE, TRUE);
  59.         m_pDropTarget->Release();
  60.         }
  61.     //End CHAPTER8MOD
  62.  
  63.     //Turn off the advise.
  64.     hr=m_pPL->QueryInterface(IID_IDataObject, (LPVOID FAR *)&pIDataObject);
  65.  
  66.     if (SUCCEEDED(hr))
  67.         pIDataObject->DUnadvise(m_dwConn);
  68.  
  69.     if (NULL!=m_pIAdviseSink)
  70.         delete m_pIAdviseSink;
  71.  
  72.     if (NULL!=m_pIPersistStorage)
  73.         m_pIPersistStorage->Release();
  74.  
  75.     if (NULL!=m_pPLAdv)
  76.         delete m_pPLAdv;
  77.  
  78.     if (NULL!=m_pPL)
  79.         m_pPL->Release();
  80.  
  81.     CoFreeUnusedLibraries();
  82.     return;
  83.     }
  84.  
  85.  
  86.  
  87.  
  88.  
  89.  
  90. /*
  91.  * CSchmooDoc::FInit
  92.  *
  93.  * Purpose:
  94.  *  Initializes an already created document window.  The client actually
  95.  *  creates the window for us, then passes that here for further
  96.  *  initialization.
  97.  *
  98.  * Parameters:
  99.  *  pDI             LPDOCUMENTINIT containing initialization parameters.
  100.  *
  101.  * Return Value:
  102.  *  BOOL            TRUE if the function succeeded, FALSE otherwise.
  103.  */
  104.  
  105. BOOL CSchmooDoc::FInit(LPDOCUMENTINIT pDI)
  106.     {
  107.     RECT            rc;
  108.     HRESULT         hr;
  109.     FORMATETC       fe;
  110.     LPDATAOBJECT    pIDataObject;
  111.  
  112.     //Change the stringtable range to our customization.
  113.     pDI->idsMin=IDS_DOCUMENTMIN;
  114.     pDI->idsMax=IDS_DOCUMENTMAX;
  115.  
  116.     //Do default initialization
  117.     if (!CDocument::FInit(pDI))
  118.         return FALSE;
  119.  
  120.     //Create the Polyline Object via COMPOBJ.DLL functions.
  121.     hr=CoCreateInstance(CLSID_Polyline6, NULL, CLSCTX_INPROC_SERVER
  122.         , IID_IPolyline6, (LPVOID FAR *)&m_pPL);
  123.  
  124.     if (FAILED(hr))
  125.         return FALSE;
  126.  
  127.     //Initialize the contained Polyline which creates a window.
  128.     GetClientRect(m_hWnd, &rc);
  129.     InflateRect(&rc, -8, -8);
  130.  
  131.     if (FAILED(m_pPL->Init(m_hWnd, &rc, WS_CHILD | WS_VISIBLE, ID_POLYLINE)))
  132.         return FALSE;
  133.  
  134.  
  135.     //Set up an advise on the Polyline.
  136.     m_pPLAdv=new CPolylineAdviseSink((LPVOID)this, (LPUNKNOWN)this);
  137.  
  138.     if (NULL==m_pPLAdv)
  139.         return FALSE;
  140.  
  141.     m_pPL->SetAdvise(m_pPLAdv);
  142.  
  143.     //Get the IPersistStorage interface on the object for loads & saves.
  144.     hr=m_pPL->QueryInterface(IID_IPersistStorage, (LPVOID FAR *)&m_pIPersistStorage);
  145.  
  146.     if (FAILED(hr))
  147.         return FALSE;
  148.  
  149.     /*
  150.      * Create an IAdviseSink and send it to the Polyline's IDataObject
  151.      * with the clipboard format for the Polyline (as in IPOLY6.H).
  152.      */
  153.  
  154.     //This is a private macro.
  155.     SETDefFormatEtc(fe, m_cf, TYMED_HGLOBAL);
  156.  
  157.     m_pIAdviseSink=new CImpIAdviseSink((LPVOID)this, (LPUNKNOWN)this);
  158.  
  159.     if (NULL==m_pIAdviseSink)
  160.         return FALSE;
  161.  
  162.     //Set up an advise for the Polyline format
  163.     hr=m_pPL->QueryInterface(IID_IDataObject, (LPVOID FAR *)&pIDataObject);
  164.  
  165.     if (FAILED(hr))
  166.         return FALSE;
  167.  
  168.     pIDataObject->DAdvise(&fe, ADVF_NODATA, m_pIAdviseSink, &m_dwConn);
  169.     pIDataObject->Release();
  170.  
  171.  
  172.     //CHAPTER8MOD
  173.     m_pDropTarget=new CDropTarget(this);
  174.  
  175.     if (NULL!=m_pDropTarget)
  176.         {
  177.         m_pDropTarget->AddRef();
  178.         RegisterDragDrop(m_hWnd, (LPDROPTARGET)m_pDropTarget);
  179.         CoLockObjectExternal((LPUNKNOWN)m_pDropTarget, TRUE, FALSE);
  180.         }
  181.     //End CHAPTER8MOD
  182.  
  183.     return TRUE;
  184.     }
  185.  
  186.  
  187.  
  188.  
  189. //IUnknown interface for all the interfaces we implement in the document
  190.  
  191. /*
  192.  * CSchmooDoc::QueryInterface
  193.  * CSchmooDoc::AddRef
  194.  * CSchmooDoc::Release
  195.  *
  196.  * Purpose:
  197.  *  IUnknown members for the CSchmooDoc implementation.
  198.  */
  199.  
  200. STDMETHODIMP CSchmooDoc::QueryInterface(REFIID riid, LPVOID FAR *ppv)
  201.     {
  202.     *ppv=NULL;
  203.  
  204.     //The document is the unknown
  205.     if (IsEqualIID(riid, IID_IUnknown))
  206.         *ppv=(LPVOID)this;
  207.  
  208.     //Return contained interfaces for others.
  209.     if (IsEqualIID(riid, IID_IPolylineAdviseSink6))
  210.         *ppv=(LPVOID)m_pPLAdv;
  211.  
  212.     if (IsEqualIID(riid, IID_IAdviseSink))
  213.         *ppv=(LPVOID)m_pIAdviseSink;
  214.  
  215.     /*
  216.      * If we actually assign an interface to ppv we need to AddRef it
  217.      * since we're returning a new pointer.
  218.      */
  219.     if (NULL!=*ppv)
  220.         {
  221.         ((LPUNKNOWN)*ppv)->AddRef();
  222.         return NOERROR;
  223.         }
  224.  
  225.     return ResultFromScode(S_FALSE);
  226.     }
  227.  
  228.  
  229. STDMETHODIMP_(ULONG) CSchmooDoc::AddRef(void)
  230.     {
  231.     return ++m_cRef;
  232.     }
  233.  
  234.  
  235. STDMETHODIMP_(ULONG) CSchmooDoc::Release(void)
  236.     {
  237.     /*
  238.      * Since CoSchmoo doesn't use documents like Component Objects, this
  239.      * doesn't do anything except provide a debugging point.
  240.      */
  241.     return --m_cRef;
  242.     }
  243.  
  244.  
  245.  
  246.  
  247.  
  248.  
  249.  
  250.  
  251. /*
  252.  * CSchmooDoc::FMessageHook
  253.  *
  254.  * Purpose:
  255.  *  Processes WM_SIZE for the document so we can resize the Polyline.
  256.  *
  257.  * Parameters:
  258.  *  <WndProc Parameters>
  259.  *  pLRes           LRESULT FAR * in which to store the return value
  260.  *                  for the message.
  261.  *
  262.  * Return Value:
  263.  *  BOOL            TRUE to prevent further processing, FALSE otherwise.
  264.  */
  265.  
  266. BOOL CSchmooDoc::FMessageHook(HWND hWnd, UINT iMsg, WPARAM wParam
  267.     , LPARAM lParam, LRESULT FAR *pLRes)
  268.     {
  269.     UINT        dx, dy;
  270.     RECT        rc;
  271.  
  272.     if (WM_SIZE==iMsg)
  273.         {
  274.         //Don't effect the Polyline size to or from minimized state.
  275.         if (SIZE_MINIMIZED!=wParam && SIZE_MINIMIZED !=m_uPrevSize)
  276.             {
  277.             //When we change size, resize any Polyline we hold.
  278.             dx=LOWORD(lParam);
  279.             dy=HIWORD(lParam);
  280.  
  281.             /*
  282.              * If we are getting WM_SIZE in response to a Polyline
  283.              * notification, then don't resize the Polyline window again.
  284.              */
  285.             if (!m_fNoSize && NULL!=m_pPL)
  286.                 {
  287.                 //Resize the polyline to fit the new client
  288.                 SetRect(&rc, 8, 8, dx-8, dy-8);
  289.                 m_pPL->RectSet(&rc, FALSE);
  290.  
  291.                 /*
  292.                  * We consider sizing something that makes the file dirty,
  293.                  * but not until we've finished the create process, which
  294.                  * is why we set fNoDirty to FALSE in WM_CREATE since we
  295.                  * get a WM_SIZE on the first creation.
  296.                  */
  297.                 if (!m_fNoDirty)
  298.                     FDirtySet(TRUE);
  299.  
  300.                 SetRect(&rc, 0, 0, dx, dy);
  301.  
  302.                 if (NULL!=m_pAdv)
  303.                     m_pAdv->OnSizeChange((LPCDocument)this, &rc);
  304.  
  305.                 m_fNoDirty=FALSE;
  306.                 }
  307.             }
  308.  
  309.         m_uPrevSize=wParam;
  310.         }
  311.  
  312.     //CHAPTER8MOD
  313.     if (WM_LBUTTONDOWN==iMsg)
  314.             {
  315.             LPDROPSOURCE    pIDropSource;
  316.             LPDATAOBJECT    pIDataObject;
  317.             HRESULT         hr;
  318.             SCODE           sc;
  319.             DWORD           dwEffect;
  320.  
  321.             pIDropSource=(LPDROPSOURCE)new CDropSource(this);
  322.  
  323.             if (NULL==pIDropSource)
  324.                 return FALSE;
  325.  
  326.             pIDropSource->AddRef();
  327.             m_fDragSource=TRUE;
  328.  
  329.             //Go get the data and start the ball rolling.
  330.             pIDataObject=TransferObjectCreate();
  331.  
  332.             hr=DoDragDrop(pIDataObject, pIDropSource
  333.                 , DROPEFFECT_COPY | DROPEFFECT_MOVE, &dwEffect);
  334.  
  335.             pIDataObject->Release();
  336.             pIDropSource->Release();
  337.  
  338.             m_fDragSource=FALSE;
  339.  
  340.             sc=GetScode(hr);
  341.  
  342.             if (DRAGDROP_S_DROP==sc && DROPEFFECT_MOVE==dwEffect)
  343.                 {
  344.                 m_pPL->New();
  345.                 FDirtySet(TRUE);
  346.                 }
  347.  
  348.             return TRUE;
  349.             }
  350.        //End CHAPTER8MOD
  351.  
  352.  
  353.     /*
  354.      * We return FALSE even on WM_SIZE so we can let the default procedure
  355.      * handle maximized MDI child windows appropriately.
  356.      */
  357.     return FALSE;
  358.     }
  359.  
  360.  
  361.  
  362.  
  363.  
  364.  
  365.  
  366.  
  367. /*
  368.  * CSchmooDoc::Clear
  369.  *
  370.  * Purpose:
  371.  *  Sets all contents in the document back to defaults with no filename.
  372.  *
  373.  * Paramters:
  374.  *  None
  375.  *
  376.  * Return Value:
  377.  *  None
  378.  */
  379.  
  380. void CSchmooDoc::Clear(void)
  381.     {
  382.     //Completely reset the polyline
  383.     m_pPL->New();
  384.  
  385.     CDocument::Clear();
  386.     return;
  387.     }
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394. /*
  395.  * CSchmooDoc::ULoad
  396.  *
  397.  * Purpose:
  398.  *  Loads a given document without any user interface overwriting the
  399.  *  previous contents of the Polyline window.  We do this by opening
  400.  *  the file and telling the Polyline to load itself from that file.
  401.  *
  402.  * Parameters:
  403.  *  fChangeFile     BOOL indicating if we're to update the window title
  404.  *                  and the filename from using this file.
  405.  *  pszFile         LPSTR to the filename to load, NULL for untitled.
  406.  *
  407.  * Return Value:
  408.  *  UINT            An error value from DOCERR_*
  409.  */
  410.  
  411. UINT CSchmooDoc::ULoad(BOOL fChangeFile, LPSTR pszFile)
  412.     {
  413.     HRESULT             hr;
  414.     LPSTORAGE           pIStorage;
  415.  
  416.     if (NULL==pszFile)
  417.         {
  418.         /*
  419.          * As a user of an IPersistStorage we have to provide all objects
  420.          * with an IStorage they can use for incremental access passing
  421.          * that storage to ::InitNew.  Here we create a temporary file
  422.          * that we don't bother holding on to.  If the object doesn't
  423.          * use it, then our ::Release destroys it immediately.
  424.          */
  425.  
  426.         hr=StgCreateDocfile(NULL, STGM_DIRECT | STGM_READWRITE | STGM_CREATE
  427.             | STGM_DELETEONRELEASE | STGM_SHARE_EXCLUSIVE, 0, &pIStorage);
  428.  
  429.         if (FAILED(hr))
  430.             return DOCERR_COULDNOTOPEN;
  431.  
  432.         m_pIPersistStorage->InitNew(pIStorage);
  433.         pIStorage->Release();
  434.  
  435.         Rename(NULL);
  436.         return DOCERR_NONE;
  437.         }
  438.  
  439.     /*
  440.      * Open a storage and pass it to the Polyline via IPersistStorage.
  441.      * We do not remain compatible with previous files saved with
  442.      * Component Schmoo.
  443.      */
  444.  
  445.     hr=StgOpenStorage(pszFile, NULL, STGM_DIRECT | STGM_READ
  446.         | STGM_SHARE_EXCLUSIVE, NULL, 0, &pIStorage);
  447.  
  448.     if (FAILED(hr))
  449.         return DOCERR_COULDNOTOPEN;
  450.  
  451.     hr=m_pIPersistStorage->Load(pIStorage);
  452.  
  453.     pIStorage->Release();
  454.  
  455.     if (FAILED(hr))
  456.         return DOCERR_READFAILURE;
  457.  
  458.     if (fChangeFile)
  459.         Rename(pszFile);
  460.  
  461.     //Importing a file makes things dirty
  462.     FDirtySet(!fChangeFile);
  463.  
  464.     return DOCERR_NONE;
  465.     }
  466.  
  467.  
  468.  
  469.  
  470.  
  471.  
  472.  
  473. /*
  474.  * CSchmooDoc::USave
  475.  *
  476.  * Purpose:
  477.  *  Writes the file to a known filename, requiring that the user has
  478.  *  previously used FileOpen or FileSaveAs in order to have a filename.
  479.  *
  480.  * Parameters:
  481.  *  uType           UINT indicating the type of file the user requested
  482.  *                  to save in the File Save As dialog.
  483.  *  pszFile         LPSTR under which to save.  If NULL, use the current name.
  484.  *
  485.  * Return Value:
  486.  *  UINT            An error value from DOCERR_*
  487.  */
  488.  
  489. UINT CSchmooDoc::USave(UINT uType, LPSTR pszFile)
  490.     {
  491.     BOOL                fRename=TRUE;
  492.     HRESULT             hr;
  493.     LPSTORAGE           pIStorage;
  494.  
  495.     if (NULL==pszFile)
  496.         {
  497.         fRename=FALSE;
  498.         pszFile=m_szFile;
  499.         }
  500.  
  501.     /*
  502.      * In Component Schmoo, we only deal with one version of data,
  503.      * so all the code in Chapter 2 Schmoo that dealt with 1.0 and
  504.      * 2.0 files has been removed.
  505.      */
  506.  
  507.     hr=StgCreateDocfile(pszFile, STGM_DIRECT | STGM_READWRITE
  508.         | STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &pIStorage);
  509.  
  510.     if (FAILED(hr))
  511.         return DOCERR_COULDNOTOPEN;
  512.  
  513.     //Tell the object to save, and also tell it that we're done.
  514.     m_pIPersistStorage->Save(pIStorage, FALSE);
  515.     m_pIPersistStorage->SaveCompleted(pIStorage);
  516.  
  517.     pIStorage->Release();
  518.  
  519.     if (FAILED(hr))
  520.         return DOCERR_WRITEFAILURE;
  521.  
  522.     //Saving makes us clean
  523.     FDirtySet(FALSE);
  524.  
  525.     if (fRename)
  526.         Rename(pszFile);
  527.  
  528.     return DOCERR_NONE;
  529.     }
  530.  
  531.  
  532.  
  533. /*
  534.  * CSchmooDoc::Undo
  535.  *
  536.  * Purpose:
  537.  *  Reverses a previous action.
  538.  *
  539.  * Parameters:
  540.  *  None
  541.  *
  542.  * Return Value:
  543.  *  None
  544.  */
  545.  
  546. void CSchmooDoc::Undo(void)
  547.     {
  548.     m_pPL->Undo();
  549.     return;
  550.     }
  551.  
  552.  
  553.  
  554.  
  555.  
  556.  
  557. /*
  558.  * CSchmooDoc::FClip
  559.  *
  560.  * Purpose:
  561.  *  Places a private format, a metafile, and a bitmap of the display
  562.  *  on the clipboard, optionally implementing Cut by deleting the
  563.  *  data in the current window after rendering.
  564.  *
  565.  * Parameters:
  566.  *  hWndFrame       HWND of the main window.
  567.  *  fCut            BOOL indicating cut (TRUE) or copy (FALSE).
  568.  *
  569.  * Return Value:
  570.  *  BOOL            TRUE if successful, FALSE otherwise.
  571.  */
  572.  
  573. BOOL CSchmooDoc::FClip(HWND hWndFrame, BOOL fCut)
  574.     {
  575.     BOOL            fRet=TRUE;
  576.     LPDATAOBJECT    pIDataObject;
  577.  
  578.     //CHAPTER8MOD
  579.     pIDataObject=TransferObjectCreate();
  580.  
  581.     if (NULL==pIDataObject)
  582.         return FALSE;
  583.     //CHAPTER8MOD
  584.  
  585.  
  586.     fRet=SUCCEEDED(OleSetClipboard(pIDataObject));
  587.     pIDataObject->Release();
  588.  
  589.     //Delete our current data if copying succeeded.
  590.     if (fRet && fCut)
  591.         {
  592.         m_pPL->New();
  593.         FDirtySet(TRUE);
  594.         }
  595.  
  596.  
  597.     return fRet;
  598.     }
  599.  
  600.  
  601.  
  602.  
  603.  
  604. /*
  605.  * CSchmooDoc::FQueryPaste
  606.  *
  607.  * Purpose:
  608.  *  Determines if we can paste data from the clipboard.
  609.  *
  610.  * Parameters:
  611.  *  None
  612.  *
  613.  * Return Value:
  614.  *  BOOL            TRUE if data is available, FALSE otherwise.
  615.  */
  616.  
  617. BOOL CSchmooDoc::FQueryPaste(void)
  618.     {
  619.     LPDATAOBJECT    pIDataObject;
  620.     BOOL            fRet;
  621.  
  622.     if (FAILED(OleGetClipboard(&pIDataObject)))
  623.         return FALSE;
  624.  
  625.     //CHAPTER8MOD
  626.     fRet=FQueryPasteFromData(pIDataObject);
  627.     //End CHAPTER8MOD
  628.  
  629.     pIDataObject->Release();
  630.     return fRet;
  631.     }
  632.  
  633.  
  634.  
  635. //CHAPTER8MOD
  636. /*
  637.  * CSchmooDoc::FQueryPasteFromData
  638.  * (Protected)
  639.  *
  640.  * Purpose:
  641.  *  Determines if we can paste data from a data object.
  642.  *
  643.  * Parameters:
  644.  *  pIDataObject    LPDATAOBJECT from which we might want to paste.
  645.  *
  646.  * Return Value:
  647.  *  BOOL            TRUE if data is available, FALSE otherwise.
  648.  */
  649.  
  650. BOOL CSchmooDoc::FQueryPasteFromData(LPDATAOBJECT pIDataObject)
  651.     {
  652.     FORMATETC       fe;
  653.  
  654.     SETDefFormatEtc(fe, m_cf, TYMED_HGLOBAL);
  655.     return (NOERROR==pIDataObject->QueryGetData(&fe));
  656.     }
  657. //End CHAPTER8MOD
  658.  
  659.  
  660.  
  661.  
  662.  
  663. /*
  664.  * CSchmooDoc::FPaste
  665.  *
  666.  * Purpose:
  667.  *  Retrieves the private data format from the clipboard and sets it
  668.  *  to the current figure in the editor window.
  669.  *
  670.  *  Note that if this function is called, then the clipboard format
  671.  *  is available because the Paste menu item is only enabled if the
  672.  *  format is present.
  673.  *
  674.  * Parameters:
  675.  *  hWndFrame       HWND of the main window.
  676.  *
  677.  * Return Value:
  678.  *  BOOL            TRUE if successful, FALSE otherwise.
  679.  */
  680.  
  681. BOOL CSchmooDoc::FPaste(HWND hWndFrame)
  682.     {
  683.     LPDATAOBJECT    pIDataObject;
  684.     BOOL            fRet;
  685.  
  686.     if (FAILED(OleGetClipboard(&pIDataObject)))
  687.         return FALSE;
  688.  
  689.     //CHAPTER8MOD
  690.     fRet=FPasteFromData(pIDataObject);
  691.     //End CHAPTER8MOD
  692.  
  693.     pIDataObject->Release();
  694.     return TRUE;
  695.     }
  696.  
  697.  
  698.  
  699. //CHAPTER8MOD
  700.  
  701.  
  702. /*
  703.  * CSchmooDoc::FPasteFromData
  704.  * (Protected)
  705.  *
  706.  * Purpose:
  707.  *  Retrieves the private data format from a data object and sets it
  708.  *  to the current figure in the editor window.
  709.  *
  710.  * Parameters:
  711.  *  pIDataObject    LPDATAOBJECT from which to paste.
  712.  *
  713.  * Return Value:
  714.  *  BOOL            TRUE if successful, FALSE otherwise.
  715.  */
  716.  
  717. BOOL CSchmooDoc::FPasteFromData(LPDATAOBJECT pIDataObject)
  718.     {
  719.     FORMATETC       fe;
  720.     STGMEDIUM       stm;
  721.     BOOL            fRet;
  722.  
  723.     SETDefFormatEtc(fe, m_cf, TYMED_HGLOBAL);
  724.     fRet=SUCCEEDED(pIDataObject->GetData(&fe, &stm));
  725.  
  726.     if (!fRet || NULL==stm.hGlobal)
  727.         return FALSE;
  728.  
  729.     if (fRet && NULL!=stm.hGlobal)
  730.         {
  731.         m_pPL->QueryInterface(IID_IDataObject, (LPVOID FAR *)&pIDataObject);
  732.         pIDataObject->SetData(&fe, &stm, TRUE);
  733.         pIDataObject->Release();
  734.  
  735.         FDirtySet(TRUE);
  736.         }
  737.  
  738.     return fRet;
  739.     }
  740.  
  741.  
  742.  
  743.  
  744. /*
  745.  * CSchmooDoc::TransferObjectCreate
  746.  * (Protected)
  747.  *
  748.  * Purpose:
  749.  *  Creates a DataTransferObject and stuffs the current Polyline
  750.  *  data into it, used for both clipboard and drag-drop operations.
  751.  *
  752.  * Parameters:
  753.  *  None
  754.  *
  755.  * Return Value:
  756.  *  LPDATAOBJECT    Pointer to the object created, NULL on failure
  757.  */
  758.  
  759. LPDATAOBJECT CSchmooDoc::TransferObjectCreate(void)
  760.     {
  761.     UINT            i;
  762.     HRESULT         hr;
  763.     STGMEDIUM       stm;
  764.     FORMATETC       fe;
  765.     LPDATAOBJECT    pIDataSrc;
  766.     LPDATAOBJECT    pIDataObject=NULL;
  767.     const UINT      cFormats=3;
  768.     static UINT     rgcf[3]={0, CF_METAFILEPICT, CF_BITMAP};
  769.     static DWORD    rgtm[3]={TYMED_HGLOBAL, TYMED_MFPICT, TYMED_GDI};
  770.  
  771.     hr=CoCreateInstance(CLSID_DataTransferObject, NULL, CLSCTX_INPROC_SERVER
  772.         , IID_IDataObject, (LPVOID FAR *)&pIDataObject);
  773.  
  774.     if (FAILED(hr))
  775.         return NULL;
  776.  
  777.     rgcf[0]=m_cf;
  778.  
  779.     hr=m_pPL->QueryInterface(IID_IDataObject, (LPVOID FAR *)&pIDataSrc);
  780.  
  781.     if (FAILED(hr))
  782.         {
  783.         pIDataObject->Release();
  784.         return NULL;
  785.         }
  786.  
  787.     for (i=0; i < cFormats; i++)
  788.         {
  789.         //Copy private data first.
  790.         SETDefFormatEtc(fe, rgcf[i], rgtm[i]);
  791.  
  792.         if (SUCCEEDED(pIDataSrc->GetData(&fe, &stm)))
  793.             pIDataObject->SetData(&fe, &stm, TRUE);
  794.         }
  795.  
  796.     pIDataSrc->Release();
  797.     return pIDataObject;    //Caller now responsible
  798.     }
  799.  
  800.  
  801.  
  802.  
  803.  
  804. /*
  805.  * CSchmooDoc::DropSelectTargetWindow
  806.  * (Protected)
  807.  *
  808.  * Purpose:
  809.  *  Creates a thin inverted frame around a window that we use to show
  810.  *  the window as a drop target.  This is a toggle function:  it uses
  811.  *  XOR to create the effect so it must be called twice to leave the
  812.  *  window as it was.
  813.  *
  814.  * Parameters:
  815.  *  None
  816.  *
  817.  * Return Value:
  818.  *  None
  819.  */
  820.  
  821. void CSchmooDoc::DropSelectTargetWindow(void)
  822.     {
  823.     HDC         hDC;
  824.     RECT        rc;
  825.     UINT        dd=3;
  826.     HWND        hWnd;
  827.  
  828.     m_pPL->Window(&hWnd);
  829.     hDC=GetWindowDC(hWnd);
  830.     GetClientRect(hWnd, &rc);
  831.  
  832.     //Frame this window with inverted pixels
  833.  
  834.     //Top
  835.     PatBlt(hDC, rc.left, rc.top, rc.right-rc.left, dd, DSTINVERT);
  836.  
  837.     //Bottom
  838.     PatBlt(hDC, rc.left, rc.bottom-dd, rc.right-rc.left, dd, DSTINVERT);
  839.  
  840.     //Left excluding regions already affected by top and bottom
  841.     PatBlt(hDC, rc.left, rc.top+dd, dd, rc.bottom-rc.top-(2*dd), DSTINVERT);
  842.  
  843.     //Right excluding regions already affected by top and bottom
  844.     PatBlt(hDC, rc.right-dd, rc.top+dd, dd, rc.bottom-rc.top-(2*dd), DSTINVERT);
  845.  
  846.     ReleaseDC(hWnd, hDC);
  847.     return;
  848.     }
  849.  
  850. //End CHAPTER8MOD
  851.  
  852.  
  853.  
  854.  
  855.  
  856.  
  857.  
  858.  
  859. /*
  860.  * CSchmooDoc::ColorSet
  861.  *
  862.  * Purpose:
  863.  *  Changes a color used in our contained Polyline.
  864.  *
  865.  * Parameters:
  866.  *  iColor          UINT index of the color to change.
  867.  *  cr              COLORREF new color.
  868.  *
  869.  * Return Value:
  870.  *  COLORREF        Previous color for the given index.
  871.  */
  872.  
  873. COLORREF CSchmooDoc::ColorSet(UINT iColor, COLORREF cr)
  874.     {
  875.     COLORREF    crRet;
  876.  
  877.     m_pPL->ColorSet(iColor, cr, &crRet);
  878.     return crRet;
  879.     }
  880.  
  881.  
  882.  
  883.  
  884.  
  885. /*
  886.  * CSchmooDoc::ColorGet
  887.  *
  888.  * Purpose:
  889.  *  Retrieves a color currently in use in the Polyline.
  890.  *
  891.  * Parameters:
  892.  *  iColor          UINT index of the color to retrieve.
  893.  *
  894.  * Return Value:
  895.  *  COLORREF        Current color for the given index.
  896.  */
  897.  
  898. COLORREF CSchmooDoc::ColorGet(UINT iColor)
  899.     {
  900.     COLORREF    crRet;
  901.  
  902.     m_pPL->ColorGet(iColor, &crRet);
  903.     return crRet;
  904.     }
  905.  
  906.  
  907.  
  908.  
  909.  
  910.  
  911. /*
  912.  * CSchmooDoc::LineStyleSet
  913.  *
  914.  * Purpose:
  915.  *  Changes the line style currently used in the Polyline
  916.  *
  917.  * Parameters:
  918.  *  iStyle          UINT index of the new line style to use.
  919.  *
  920.  * Return Value:
  921.  *  UINT            Previous line style.
  922.  */
  923.  
  924.  
  925. UINT CSchmooDoc::LineStyleSet(UINT iStyle)
  926.     {
  927.     UINT    i;
  928.  
  929.     m_pPL->LineStyleSet(iStyle, &i);
  930.     return i;
  931.     }
  932.  
  933.  
  934.  
  935.  
  936.  
  937.  
  938.  
  939. /*
  940.  * CSchmooDoc::LineStyleGet
  941.  *
  942.  * Purpose:
  943.  *  Retrieves the line style currently used in the Polyline
  944.  *
  945.  * Parameters:
  946.  *  None
  947.  *
  948.  * Return Value:
  949.  *  UINT            Current line style.
  950.  */
  951.  
  952.  
  953. UINT CSchmooDoc::LineStyleGet(void)
  954.     {
  955.     UINT    i;
  956.  
  957.     m_pPL->LineStyleGet(&i);
  958.     return i;
  959.     }
  960.  
  961.  
  962.  
  963. //CPolylineAdviseSink moved to IADVSINK.CPP
  964.